package cn.com.cifi.mars.service.impl;
import cn.com.cifi.mars.bean.dto.returnPlan.ReturnCoefficientDetailDto;
import cn.com.cifi.mars.bean.vo.returnPlan.ReturnPlanReturnCoefficientDetailVo;
import cn.com.cifi.mars.common.exception.MsgException;
import cn.com.cifi.mars.constant.CodeEnum;
import cn.com.cifi.mars.constant.IsDeleteEnum;
import cn.com.cifi.mars.constant.ReturnVersionTypeEnum;
import cn.com.cifi.mars.constant.VersionStatusEnum;
import cn.com.cifi.mars.entity.ProjectReturnCoefficient;
import cn.com.cifi.mars.entity.ReturnCoefficientDetail;
import cn.com.cifi.mars.entity.ReturnPlanVersion;
import cn.com.cifi.mars.entity.ReturnPlanVersionCoefficient;
import cn.com.cifi.mars.entity.common.IdmUser;
import cn.com.cifi.mars.mapper.mars.ReturnPlanVersionCoefficientMapper;
import cn.com.cifi.mars.mapper.mars.SignPlanVersionDetailMapper;
import cn.com.cifi.mars.mapper.wrapper.ProjectReturnCoefficientWrapper;
import cn.com.cifi.mars.mapper.wrapper.ReturnCoefficientDetailWrapper;
import cn.com.cifi.mars.mapper.wrapper.ReturnPlanVersionCoefficientWrapper;
import cn.com.cifi.mars.service.ReturnPlanVersionCoefficientService;
import cn.com.cifi.mars.util.DateUtils;
import cn.com.cifi.mars.util.LocalDateTimeUtils;
import cn.com.cifi.mars.util.UUIDUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 回款计划版本系数表 服务实现类
 * </p>
 *
 * @author JingYuanXiang
 * @since 2020-11-05
 */
@Slf4j
@Service
public class ReturnPlanVersionCoefficientServiceImpl extends ServiceImpl<ReturnPlanVersionCoefficientMapper, ReturnPlanVersionCoefficient> implements ReturnPlanVersionCoefficientService {

    @Autowired
    private ReturnPlanVersionCoefficientMapper returnPlanVersionCoefficientMapper;
    @Autowired
    private ReturnPlanVersionCoefficientWrapper returnPlanVersionCoefficientWrapper;
    @Autowired
    private ProjectReturnCoefficientWrapper projectReturnCoefficientWrapper;
    @Autowired
    private ReturnCoefficientDetailWrapper returnCoefficientDetailWrapper;
    @Autowired
    private SignPlanVersionDetailMapper signPlanVersionDetailMapper;

    /**
     * 获取创建回款计划版本来源回款系数名称
     * @param projectId 项目id
     * @param signPlanVersionId
     * @return
     */
    @Override
    public String getCreateSourceCoefficient(String projectId, String signPlanVersionId) {
        //回款系数名称
        String returnCoefficientName = "";
        Set<ProjectReturnCoefficient> returnCoefficientSet = new HashSet<>();

        //获取各版本类型中项目回款系数最新版（key:版本类型编码，value:项目回款系数）
        Map<String,ProjectReturnCoefficient> projectReturnCoefficientMap = getReturnCoefficientMapByType(projectId);
        //各项目回款系数种各标椎业态的回款系数id（key:版本类型，(key:标椎业态编码,value:项目回款系数）
        Map<String,Map<String,String>> coefficientDetailMap = getCoefficientDetailMapByTypeAndProProduct(projectReturnCoefficientMap);
        //获取调整版项目回款系数
        ProjectReturnCoefficient projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
        //是否使用调整版
        boolean whether = whetherUseAdjustment(projectCoefficient);

        //获取标准业态列表
        List<String> proProductCodeList = signPlanVersionDetailMapper.selectProProductCodeList(signPlanVersionId,IsDeleteEnum.NO.getKey());
        //按照规则计算回款系数取数,生成回款计划版本回款系数
        if(whether){
            for (String proProductCode : proProductCodeList){
                Map<String, String> coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
                //使用项目最新调整版标准业态的回款系数
                if(null != coefficientDetailIdMap && coefficientDetailIdMap.containsKey(proProductCode)){
                    projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
                    returnCoefficientSet.add(projectCoefficient);
                }else {
                    coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.PRACTICAL.getKey());
                    //项目标准业态无调整回款系数，但项目有实际版回款系数时，使用项目最新实际版已生效的回款系数
                    if(null != coefficientDetailIdMap &&  coefficientDetailIdMap.containsKey(proProductCode)){
                        projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
                        returnCoefficientSet.add(projectCoefficient);
                    }else {
                        coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
                        //项目标准业态无生效的实际版和调整版回款系数时，使用项目最新投资正式版标准业态的回款系数
                        if(null != coefficientDetailIdMap && coefficientDetailIdMap.containsKey(proProductCode)){
                            projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
                            returnCoefficientSet.add(projectCoefficient);
                        }else {
                            throw new MsgException(CodeEnum.NOT_USE_RETURN_COFFICIENT_VERSION_ERROR);
                        }
                    }
                }
            }
        }else {
            //没有两个月内的调整版回款系数
            for (String proProductCode : proProductCodeList){
                Map<String, String> coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.PRACTICAL.getKey());
                //使用项目最新实际版标准业态的回款系数
                if(null != coefficientDetailIdMap && coefficientDetailIdMap.containsKey(proProductCode)){
                    projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.PRACTICAL.getKey());
                    returnCoefficientSet.add(projectCoefficient);
                }else {
                    coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
                    //项目标准业态无已生效的实际版回款系数，但项目有调整版回款系数时，使用项目最新调整版标准业态的 回款系数
                    if(null != coefficientDetailIdMap &&  coefficientDetailIdMap.containsKey(proProductCode)){
                        projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
                        returnCoefficientSet.add(projectCoefficient);
                    }else {
                        coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
                        //项目标准业态无生效的实际版和调整版回款系数时，使用项目最新投资正式版标准业态的回款系数
                        if(null != coefficientDetailIdMap && coefficientDetailIdMap.containsKey(proProductCode)){
                            projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
                            returnCoefficientSet.add(projectCoefficient);
                        }else {
                            throw new MsgException(CodeEnum.NOT_USE_RETURN_COFFICIENT_VERSION_ERROR);
                        }
                    }
                }
            }
        }
        if(CollectionUtils.isEmpty(returnCoefficientSet)){
            throw new MsgException(CodeEnum.CREATE_RETURN_PLAN_NOT_CURRENT_MONTH_SIGN_PLAN_VERSION_ERROR);
        }
        for (ProjectReturnCoefficient returnCoefficient : returnCoefficientSet){
            String coefficientName = getProjectReturnCoefficientVersionName(returnCoefficient);
            returnCoefficientName = returnCoefficientName.concat(coefficientName + "、");
        }
        returnCoefficientName = returnCoefficientName.substring(0, returnCoefficientName.length() - 1);
        return returnCoefficientName;
    }

    /**
     * 创建回款系数
     * 1、项目有两个月内的调整版回款系数，项目所有标准业态使用调整版回款系数;(两个月：第一次被审批通过回款计划使用后的当月与下个月)
     * 附加：最新版调整版回款系数没有被任何审批通过回款计划使用，项目所有标准业态使用调整版回款系数
     * 2、没有两个月内的调整版回款系数，项目标准业态有已生效的实际版回款系数时，使用项目最新实际版标准业态的回款系数;
     * 3、没有两个月内的调整版回款系数，项目标准业态无已生效的实际版回款系数，但项目有调整版回款系数时，使用项目最新调整版标准业态的 回款系数;
     * 4、项目标准业态无生效的实际版和调整版回款系数时，使用项目最新投资正式版标准业态的回款系数;
     * 5、项目没有任何回款系数版本时，不能新建回款计划版本；（上线时需要对所有项目初始化一版回款系数）;
     * @param returnPlanVersion 回款计划版本数据
     * @param user 用户
     */
    @Override
    public void createList(ReturnPlanVersion returnPlanVersion,IdmUser user) {
        //参数校验
        if(null == returnPlanVersion || null == user){
            throw new MsgException(CodeEnum.REQUEST_PARAM_NOT_FULL_ERROR);
        }
        //回款计划版本系数列表
        List<ReturnPlanVersionCoefficient> returnPlanVersionCoefficientList = new ArrayList<>();

        //获取项目id
        String projectId = returnPlanVersion.getProjectId();
        //获取各版本类型中项目回款系数最新版（key:版本类型编码，value:项目回款系数）
        Map<String,ProjectReturnCoefficient> projectReturnCoefficientMap = getReturnCoefficientMapByType(projectId);
        //各项目回款系数种各标椎业态的回款系数id（key:版本类型，(key:标椎业态编码,value:项目回款系数）
        Map<String,Map<String,String>> coefficientDetailMap = getCoefficientDetailMapByTypeAndProProduct(projectReturnCoefficientMap);
        //获取调整版项目回款系数
        ProjectReturnCoefficient projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
        //是否使用调整版
        boolean whether = whetherUseAdjustment(projectCoefficient);

        //获取标准业态列表
        List<String> proProductCodeList = signPlanVersionDetailMapper.selectProProductCodeList(returnPlanVersion.getSignPlanVersionId(),IsDeleteEnum.NO.getKey());
        //按照规则计算回款系数取数,生成回款计划版本回款系数
        if(whether){
            for (String proProductCode : proProductCodeList){
                Map<String, String> coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
                //使用项目最新调整版标准业态的回款系数
                if(null != coefficientDetailIdMap && coefficientDetailIdMap.containsKey(proProductCode)){
                    String returnCoefficientDetailId = coefficientDetailIdMap.get(proProductCode);
                    projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
                    ReturnPlanVersionCoefficient versionCoefficient = this.create(returnPlanVersion.getId(),returnCoefficientDetailId, projectCoefficient, user);
                    returnPlanVersionCoefficientList.add(versionCoefficient);
                }else {
                    coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.PRACTICAL.getKey());
                    //项目标准业态无调整回款系数，但项目有实际版回款系数时，使用项目最新实际版已生效的回款系数
                    if(null != coefficientDetailIdMap &&  coefficientDetailIdMap.containsKey(proProductCode)){
                        String returnCoefficientDetailId = coefficientDetailIdMap.get(proProductCode);
                        projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
                        ReturnPlanVersionCoefficient versionCoefficient = this.create(returnPlanVersion.getId(), returnCoefficientDetailId, projectCoefficient, user);
                        returnPlanVersionCoefficientList.add(versionCoefficient);
                    }else {
                        coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
                        //项目标准业态无生效的实际版和调整版回款系数时，使用项目最新投资正式版标准业态的回款系数
                        if(null != coefficientDetailIdMap && coefficientDetailIdMap.containsKey(proProductCode)){
                            String returnCoefficientDetailId = coefficientDetailIdMap.get(proProductCode);
                            projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
                            ReturnPlanVersionCoefficient versionCoefficient = this.create(returnPlanVersion.getId(), returnCoefficientDetailId, projectCoefficient, user);
                            returnPlanVersionCoefficientList.add(versionCoefficient);
                        }else {
                            throw new MsgException(CodeEnum.NOT_USE_RETURN_COFFICIENT_VERSION_ERROR);
                        }
                    }
                }
            }
        }else {
            //没有两个月内的调整版回款系数
            for (String proProductCode : proProductCodeList){
                Map<String, String> coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.PRACTICAL.getKey());
                //使用项目最新实际版标准业态的回款系数
                if(null != coefficientDetailIdMap && coefficientDetailIdMap.containsKey(proProductCode)){
                    String returnCoefficientDetailId = coefficientDetailIdMap.get(proProductCode);
                    projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.PRACTICAL.getKey());
                    ReturnPlanVersionCoefficient versionCoefficient = this.create(returnPlanVersion.getId(),returnCoefficientDetailId, projectCoefficient, user);
                    returnPlanVersionCoefficientList.add(versionCoefficient);
                }else {
                    coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
                    //项目标准业态无已生效的实际版回款系数，但项目有调整版回款系数时，使用项目最新调整版标准业态的 回款系数
                    if(null != coefficientDetailIdMap &&  coefficientDetailIdMap.containsKey(proProductCode)){
                        String returnCoefficientDetailId = coefficientDetailIdMap.get(proProductCode);
                        projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
                        ReturnPlanVersionCoefficient versionCoefficient = this.create(returnPlanVersion.getId(), returnCoefficientDetailId, projectCoefficient, user);
                        returnPlanVersionCoefficientList.add(versionCoefficient);
                    }else {
                        coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
                        //项目标准业态无生效的实际版和调整版回款系数时，使用项目最新投资正式版标准业态的回款系数
                        if(null != coefficientDetailIdMap && coefficientDetailIdMap.containsKey(proProductCode)){
                            String returnCoefficientDetailId = coefficientDetailIdMap.get(proProductCode);
                            projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
                            ReturnPlanVersionCoefficient versionCoefficient = this.create(returnPlanVersion.getId(), returnCoefficientDetailId, projectCoefficient, user);
                            returnPlanVersionCoefficientList.add(versionCoefficient);
                        }else {
                            throw new MsgException(CodeEnum.NOT_USE_RETURN_COFFICIENT_VERSION_ERROR);
                        }
                    }
                }
            }
        }

        if(CollectionUtils.isEmpty(returnPlanVersionCoefficientList)){
            throw new MsgException(CodeEnum.REQUEST_PARAM_NOT_FULL_ERROR);
        }
        this.saveBatch(returnPlanVersionCoefficientList);
    }

    @Override
    public void createByInvestmentList(ReturnPlanVersion returnPlanVersion, IdmUser user) {
        //参数校验
        if(null == returnPlanVersion || null == user){
            throw new MsgException(CodeEnum.REQUEST_PARAM_NOT_FULL_ERROR);
        }
        //回款计划版本系数列表
        List<ReturnPlanVersionCoefficient> returnPlanVersionCoefficientList = new ArrayList<>();

        //获取项目id
        String projectId = returnPlanVersion.getProjectId();
        //获取投资版项目回款系数最新版（key:版本类型编码，value:项目回款系数）
        Map<String,ProjectReturnCoefficient> projectReturnCoefficientMap = new HashMap<>();
        //查询最新投资正式版回款系数版本
        ProjectReturnCoefficient investOfficialReturnCoefficient = projectReturnCoefficientWrapper.selectLatestByProjectIdAndVersionTypeAndVersionState(
                projectId, ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey(), VersionStatusEnum.SYSGENERATION.getKey(), IsDeleteEnum.NO.getKey());
        if(null != investOfficialReturnCoefficient){
            projectReturnCoefficientMap.put(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey(),investOfficialReturnCoefficient);
        }
        //各项目回款系数种各标椎业态的回款系数id（key:版本类型，(key:标椎业态编码,value:项目回款系数）
        Map<String,Map<String,String>> coefficientDetailMap = getCoefficientDetailMapByTypeAndProProduct(projectReturnCoefficientMap);

        //获取标准业态列表
        List<String> proProductCodeList = signPlanVersionDetailMapper.selectProProductCodeList(returnPlanVersion.getSignPlanVersionId(),IsDeleteEnum.NO.getKey());
        for (String proProductCode : proProductCodeList){
            Map<String, String> coefficientDetailIdMap = coefficientDetailMap.get(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
            //使用项目最新投资正式版标准业态的回款系数
            if(null != coefficientDetailIdMap && coefficientDetailIdMap.containsKey(proProductCode)){
                String returnCoefficientDetailId = coefficientDetailIdMap.get(proProductCode);
                ProjectReturnCoefficient projectCoefficient = projectReturnCoefficientMap.get(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
                ReturnPlanVersionCoefficient versionCoefficient = this.create(returnPlanVersion.getId(), returnCoefficientDetailId, projectCoefficient, user);
                returnPlanVersionCoefficientList.add(versionCoefficient);
            }else {
                throw new MsgException(CodeEnum.NOT_USE_RETURN_COFFICIENT_VERSION_ERROR);
            }
        }

        if(CollectionUtils.isEmpty(returnPlanVersionCoefficientList)){
            throw new MsgException(CodeEnum.REQUEST_PARAM_NOT_FULL_ERROR);
        }
        this.saveBatch(returnPlanVersionCoefficientList);
    }

    /**
     * 是否使用调整版
     * @param projectCoefficient 项目回款系数
     * @return
     */
    private boolean whetherUseAdjustment(ProjectReturnCoefficient projectCoefficient) {
        if(null == projectCoefficient){
            return false;
        }
        //获取项目回款系数最早被回款计划使用的时间
        LocalDateTime earliestTime = returnPlanVersionCoefficientWrapper.selectEarliestCreateTimeByProjectCoefficientId(projectCoefficient.getId(), IsDeleteEnum.NO.getKey());
        if(null == earliestTime){
            return true;
        }
        int monthNum = LocalDateTimeUtils.monthDiff(earliestTime, LocalDateTime.now());
        if(monthNum <= 2){
            return true;
        }
        return false;
    }

    /**
     * 获取回款系数详情列表
     * @param returnPlanVersionId 回款计划版本id
     * @return
     */
    @Override
    public List<ReturnCoefficientDetail> getReturnCoefficientDetailListByReturnPlanVersionId(String returnPlanVersionId) {
        return returnPlanVersionCoefficientMapper.selectReturnCoefficientDetailListByReturnPlanVersionId(returnPlanVersionId,IsDeleteEnum.NO.getKey());
    }

    @Override
    public List<ReturnPlanReturnCoefficientDetailVo> getReturnCoefficientDetailList(String returnPlanVersionId) {
        //获取回款计划系数列表
        List<ReturnPlanVersionCoefficient> returnPlanVersionCoefficientList = returnPlanVersionCoefficientWrapper.selectListByReturnPlanVersionId(returnPlanVersionId, IsDeleteEnum.NO.getKey());
        //获取回款计划系数详情列表
        List<ReturnCoefficientDetail> returnCoefficientDetailList = returnPlanVersionCoefficientMapper.selectReturnCoefficientDetailListByReturnPlanVersionId(returnPlanVersionId, IsDeleteEnum.NO.getKey());
        Map<String, ReturnCoefficientDetail> returnCoefficientDetailMap = returnCoefficientDetailList.stream().collect(Collectors.toMap(ReturnCoefficientDetail::getId, s -> s));

        List<ReturnPlanReturnCoefficientDetailVo> voList = new ArrayList<>();

        for (ReturnPlanVersionCoefficient returnPlanVersionCoefficient : returnPlanVersionCoefficientList){
            ReturnPlanReturnCoefficientDetailVo vo = new ReturnPlanReturnCoefficientDetailVo();
            ReturnCoefficientDetail returnCoefficientDetail = returnCoefficientDetailMap.get(returnPlanVersionCoefficient.getReturnCoefficientDetailId());

            vo.setProProductType(returnCoefficientDetail.getProProductType());
            vo.setVersionName(returnPlanVersionCoefficient.getProjectCoefficientName());
            vo.setOneMonth(returnCoefficientDetail.getOneMonth());
            vo.setTwoMonth(returnCoefficientDetail.getTwoMonth());
            vo.setThreeMonth(returnCoefficientDetail.getThreeMonth());
            vo.setFourMonth(returnCoefficientDetail.getFourMonth());
            vo.setFiveMonth(returnCoefficientDetail.getFiveMonth());
            vo.setSixMonth(returnCoefficientDetail.getSixMonth());
            vo.setSevenMonth(returnCoefficientDetail.getSevenMonth());
            vo.setEightMonth(returnCoefficientDetail.getEightMonth());
            vo.setNineMonth(returnCoefficientDetail.getNineMonth());
            vo.setTenMonth(returnCoefficientDetail.getTenMonth());
            vo.setElevenMonth(returnCoefficientDetail.getElevenMonth());
            vo.setTwelveMonth(returnCoefficientDetail.getTwelveMonth());
            vo.setThirteenMonth(returnCoefficientDetail.getThirteenMonth());
            vo.setFourteenMonth(returnCoefficientDetail.getFourteenMonth());
            vo.setFifteenMonth(returnCoefficientDetail.getFifteenMonth());
            vo.setSixteenMonth(returnCoefficientDetail.getSixteenMonth());
            vo.setSeventeenMonth(returnCoefficientDetail.getSeventeenMonth());
            vo.setEighteenMonth(returnCoefficientDetail.getEighteenMonth());
            vo.setNineteenMonth(returnCoefficientDetail.getNineteenMonth());
            vo.setTwentyMonth(returnCoefficientDetail.getTwentyMonth());
            vo.setTwentyOneMonth(returnCoefficientDetail.getTwentyOneMonth());
            vo.setTwentyTwoMonth(returnCoefficientDetail.getTwentyTwoMonth());
            vo.setTwentyThreeMonth(returnCoefficientDetail.getTwentyThreeMonth());
            vo.setTwentyFourMonth(returnCoefficientDetail.getTwentyFourMonth());
            //计算合计
            vo.calculationTotal();
            voList.add(vo);
        }
        return voList;
    }

    /**
     * 获取回款系数详情列表
     * @param returnPlanVersionIdList
     * @return
     */
    @Override
    public List<ReturnCoefficientDetailDto> getReturnCoefficientDetailListByReturnPlanVersionIdList(List<String> returnPlanVersionIdList) {
        return returnPlanVersionCoefficientMapper.selectReturnCoefficientDetailListByReturnPlanVersionIdList(returnPlanVersionIdList,IsDeleteEnum.NO.getKey());
    }

    /**
     * 获取各版本类型项目回款系数最新版Map
     * （key:版本类型编码，value:项目回款系数）
     * @param projectId 项目id
     * @return
     */
    private Map<String, ProjectReturnCoefficient> getReturnCoefficientMapByType(String projectId) {
        Map<String,ProjectReturnCoefficient> map = new HashMap<>();

        //查询最新调整版回款系数版本
        ProjectReturnCoefficient adjustmentReturnCoefficient = projectReturnCoefficientWrapper.selectLatestByProjectIdAndVersionTypeAndVersionState(
                projectId, ReturnVersionTypeEnum.ADJUSTMENT.getKey(), VersionStatusEnum.SUCCESSAPPROVED.getKey(), IsDeleteEnum.NO.getKey());
        //查询最新实际版回款系数版本
        ProjectReturnCoefficient practicalReturnCoefficient = projectReturnCoefficientWrapper.selectLatestByProjectIdAndVersionTypeAndVersionState(
                projectId, ReturnVersionTypeEnum.PRACTICAL.getKey(), VersionStatusEnum.SYSGENERATION.getKey(), IsDeleteEnum.NO.getKey());
        //查询最新投资正式版回款系数版本
        ProjectReturnCoefficient investOfficialReturnCoefficient = projectReturnCoefficientWrapper.selectLatestByProjectIdAndVersionTypeAndVersionState(
                projectId, ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey(), VersionStatusEnum.SYSGENERATION.getKey(), IsDeleteEnum.NO.getKey());
        if(null != adjustmentReturnCoefficient){
            map.put(ReturnVersionTypeEnum.ADJUSTMENT.getKey(),adjustmentReturnCoefficient);
        }
        if(null != practicalReturnCoefficient){
            map.put(ReturnVersionTypeEnum.PRACTICAL.getKey(),practicalReturnCoefficient);
        }
        if(null != investOfficialReturnCoefficient){
            map.put(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey(),investOfficialReturnCoefficient);
        }
        return map;
    }

    /**
     * 各项目回款系数种各标椎业态的回款系数id
     * （key:版本类型，(key:标椎业态编码,value:回款系数详情id)）
     * @param returnCoefficientMap
     * @return
     */
    private Map<String, Map<String, String>> getCoefficientDetailMapByTypeAndProProduct(Map<String,ProjectReturnCoefficient> returnCoefficientMap) {
        Map<String,Map<String,String>> coefficientDetailMap = new HashMap<>();

        //投资正式版、调整版、实际版
        List<String> returnVersionTypeList = Arrays
                .asList(ReturnVersionTypeEnum.ADJUSTMENT.getKey(), ReturnVersionTypeEnum.PRACTICAL.getKey(), ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
        for (String returnVersionType : returnVersionTypeList){
            //项目回款系数
            ProjectReturnCoefficient returnCoefficient = returnCoefficientMap.get(returnVersionType);
            if(null == returnCoefficient){
                continue;
            }

            //(key:标椎业态编码,value:回款系数详情id)
            Map<String, String> coefficientDetailIdMap = new HashMap<>();

            //查询调整版回款系数详情列表
            List<ReturnCoefficientDetail> coefficientDetailList = returnCoefficientDetailWrapper
                    .selectByCoefficientId(returnCoefficient.getId(),IsDeleteEnum.NO.getKey());
            //对实际版回款系数特殊处理 -> 将已生效的标椎业态写入Map
            if(ReturnVersionTypeEnum.PRACTICAL.getKey().equals(returnVersionType)){
                coefficientDetailIdMap = coefficientDetailList.stream()
                        .filter(s-> s.getEffectiveDate() != null && s.getEffectiveDate().compareTo(LocalDateTime.now()) <= 0)
                        .collect(Collectors.toMap(ReturnCoefficientDetail::getProProductCode, ReturnCoefficientDetail::getId));
            }else {
                coefficientDetailIdMap = coefficientDetailList.stream()
                        .collect(Collectors.toMap(ReturnCoefficientDetail::getProProductCode, ReturnCoefficientDetail::getId));
            }
            coefficientDetailMap.put(returnVersionType,coefficientDetailIdMap);
        }
        return coefficientDetailMap;
    }

    /**
     * 调整版回款系数生成回款计划版本回款系数
     * @param returnPlanVersionId 回款计划版本id
     * @param returnCoefficientDetailId 回款系数详情id
     * @param projectReturnCoefficient 项目回款系数版本数据
     * @param user 用户
     * @return
     */
    private ReturnPlanVersionCoefficient create(String returnPlanVersionId, String returnCoefficientDetailId,ProjectReturnCoefficient projectReturnCoefficient, IdmUser user) {

        //回款系数版本名称
        String coefficientVersionName = this.getProjectReturnCoefficientVersionName(projectReturnCoefficient);

        ReturnPlanVersionCoefficient returnPlanVersionCoefficient = new ReturnPlanVersionCoefficient();
        returnPlanVersionCoefficient.setId(UUIDUtils.create());
        returnPlanVersionCoefficient.setReturnPlanVersionId(returnPlanVersionId);
        returnPlanVersionCoefficient.setProjectCoefficientId(projectReturnCoefficient.getId());
        returnPlanVersionCoefficient.setProjectCoefficientName(coefficientVersionName);
        returnPlanVersionCoefficient.setReturnCoefficientDetailId(returnCoefficientDetailId);
        returnPlanVersionCoefficient.setCreateBy(user.getAlias());
        returnPlanVersionCoefficient.setCreateTime(LocalDateTime.now());
        returnPlanVersionCoefficient.setUpdateBy(user.getAlias());
        returnPlanVersionCoefficient.setUpdateTime(LocalDateTime.now());
        returnPlanVersionCoefficient.setIsDelete(IsDeleteEnum.NO.getKey());
        return returnPlanVersionCoefficient;
    }

    /**
     * 获取回款系数版本名称
     * 投资正式版名称规则（无归属月份）：投资正式版V(n)-创建日期；
     * 调整版名称规则（有归属月）：调整版V(n)-审批通过日期；
     * 实际版名称规则（有归属月）：归属月实际版V(n)-创建日期。
     * @param projectReturnCoefficient 项目回款系数版本
     * @return
     */
    private String getProjectReturnCoefficientVersionName(ProjectReturnCoefficient projectReturnCoefficient) {
        String versionType = projectReturnCoefficient.getVersionType();
        String versionNum = projectReturnCoefficient.getVersionNum();


        if(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey().equals(versionType)){
            LocalDateTime createTime = projectReturnCoefficient.getCreateTime();
            String time = LocalDateTimeUtils.formatTime(createTime, DateUtils.DATE_KEY_SMALL_STR);

            return ReturnVersionTypeEnum.INVEST_OFFICIAL.getValue() + versionNum + "-" + time;
        }else if (ReturnVersionTypeEnum.ADJUSTMENT.getKey().equals(versionType)){
            LocalDateTime approvalTime = projectReturnCoefficient.getApprovalTime();
            String time = LocalDateTimeUtils.formatTime(approvalTime, DateUtils.DATE_KEY_SMALL_STR);

            return ReturnVersionTypeEnum.ADJUSTMENT.getValue() + versionNum + "-" + time;
        }else if (ReturnVersionTypeEnum.PRACTICAL.getKey().equals(versionType)){
            String affiliationMonth = projectReturnCoefficient.getAffiliationMonth().replace("-","");
            LocalDateTime createTime = projectReturnCoefficient.getCreateTime();
            String time = LocalDateTimeUtils.formatTime(createTime, DateUtils.DATE_KEY_SMALL_STR);

            return affiliationMonth + "月" +ReturnVersionTypeEnum.PRACTICAL.getValue()+ versionNum + "-" + time;
        }
        return null;

    }
}
